package org.ala.tcp_feign_common.logs;

import java.util.HashMap;
import java.util.Map;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;

/**
 * 日志工厂
 * 
 * @author 骆毅(ala)
 * @date 2024年2月4日
 */
public class LoggerFactory {
	/**
	 * 日志根目录
	 */
	static String ROOT_LOG_PATH = "logs";
	
	
	/**
	 * 文件Appender
	 */
	protected static FileAppender<ILoggingEvent> fileAppender(String dirPath, String logName, int historyDay, LoggerContext lc) {
		//		日志完整路径（每天一个日志，最多保留7天）
		String logPath = ROOT_LOG_PATH + "/" + dirPath + (dirPath.endsWith("/") || dirPath.equals("") ? "" : "/") + logName + ".log";
		
		FileAppender<ILoggingEvent> fileAppender = null;
        //	如果保留历史天数 > 0
        if (historyDay > 0) {
        	RollingFileAppender<ILoggingEvent> rollingFileAppender = new RollingFileAppender<ILoggingEvent>();
        	fileAppender = rollingFileAppender;
        	rollingFileAppender.setFile(logPath);
            //	设置历史日志
            TimeBasedRollingPolicy<ILoggingEvent> policy = new TimeBasedRollingPolicy<ILoggingEvent>();
            policy.setFileNamePattern(ROOT_LOG_PATH + "/" + dirPath + (dirPath.endsWith("/") || dirPath.equals("") ? "" : "/") + logName + "-%d{yyyy-MM-dd}.log");
            policy.setMaxHistory(historyDay);
            policy.setParent(fileAppender);
            policy.setContext(lc);
            rollingFileAppender.setRollingPolicy(policy);
            policy.start();
        }
        //	否则普通文件append即可
        else {
        	fileAppender = new FileAppender<>();
        	fileAppender.setFile(logPath);
        }
        
        //	日志输出格式
        PatternLayoutEncoder ple = new PatternLayoutEncoder();
        ple.setPattern("%date %level [%thread] %logger{10} [%file:%line] [" + logName + "] %msg%n");
        ple.setContext(lc);
        ple.start();
        fileAppender.setEncoder(ple);
        fileAppender.setContext(lc);
        fileAppender.start();
        
        return fileAppender;
	}
	
	
	/**
	 * 控制台输出
	 */
	protected static ConsoleAppender<ILoggingEvent> consoleAppender(String logName, LoggerContext lc) {
		ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
		
        //	日志输出格式
        PatternLayoutEncoder ple = new PatternLayoutEncoder();
        ple.setPattern("%date %level [%thread] %logger{10} [%file:%line] [" + logName + "] %msg%n");
        ple.setContext(lc);
        ple.start();
        consoleAppender.setEncoder(ple);
        consoleAppender.setContext(lc);
        consoleAppender.start();
		return consoleAppender;
	}


	/**
	 * 创建日志
	 */
	public static Logger createLogger(String dirPath, String logName, Level level, int historyDay) {
		if (dirPath == null || dirPath.length() == 0) {dirPath = "";}
		
		LoggerContext lc = (LoggerContext) org.slf4j.LoggerFactory.getILoggerFactory();

        //	文件记录日志
        FileAppender<ILoggingEvent> fileAppender = fileAppender(dirPath, logName, historyDay, lc);
        
        //	控制台输出
        ConsoleAppender<ILoggingEvent> consoleAppender = consoleAppender(logName, lc);

        //	创建logger
        Logger logger = (Logger) org.slf4j.LoggerFactory.getLogger(dirPath + "." + logName);
        logger.addAppender(fileAppender);
        logger.addAppender(consoleAppender);
        logger.setLevel(level);
        logger.setAdditive(false); /* set to true if root should log too */

        return logger;
	}
	
	
	static Map<String, Logger> logHolder = new HashMap<String, Logger>();
	/**
	 * 取serviceId对应的日志
	 */
	public static Logger getLogger(String dir, String file, int historyDay) {
		//	日志key
		String key = dir + ":" + file;
		synchronized (key.intern()) {
			Logger log = logHolder.get(key);
			if (log == null) {
				log = createLogger(dir, file, Level.INFO, historyDay);
				logHolder.put(key, log);
			}
			return log;
		}
	}
	/**
	 * 取serviceId对应的日志
	 */
	public static Logger getLogger(String dir, String file) {
		//	日志key
		String key = dir + ":" + file;
		synchronized (key.intern()) {
			Logger log = logHolder.get(key);
			if (log == null) {
				log = createLogger(dir, file, Level.INFO, 7);
				logHolder.put(key, log);
			}
			return log;
		}
	}
}
